Option Explicit

    '<Example Screen>
    '----------------------------------------------------------------------|
    '합계 : Rate                                |Year    |Month   |Week    |
    '                                           |2013             |Total   |
    '                                           |Jan              |        |
    'Region  |Subsidiary                        |W01      W02     |        |
    '----------------------------------------------------------------------|
    'CHINA   |LGECH                             |10       20      |30      |
    '        |LGEHN                             |20       30      |50      |
    '----------------------------------------------------------------------|
    'Total                                      |30       50      |80      |
    '----------------------------------------------------------------------|
    
    
    '<Area Marker>
    '----------------------------------------------------------------------|
    'A                                          |B                         |    'A = 합계 : Rate영역, B = Year, Month, Week 등의 컬럼필드의 드롭다운 리스트 출력되는 영역
    'C                                          |D                |E       |    'C = 빈공간, D = 열필드 필드아이템 출력 공간, E = RowGrand가 True일 때 RowGrand의 열필드 영역
    'F                                          |                 |        |    'F = 행필드 컬럼필드의 드롭다운 리스트 영역
    '----------------------------------------------------------------------|
    'G                                          |H                |I       |    'G = 행필드 필드아이템 출력 공간, H = DataBodyRange에서 Total은 뺀 영역, I = DataBodyRange에서 RowGrand 영역
    '----------------------------------------------------------------------|
    'J                                          |K                |L       |    'J = ColumnGrand가 True일 때 ColumnGrand의 행필드 영역, K = DataBodyRange에서 ColumnGrand영역, L = RowGrand와 ColumnGrand가 만나는 부분
    '----------------------------------------------------------------------|
    
    '*A와 B영역은 보통 Rows(n).Hidden으로 숨기기 때문에 일반적으로 관심밖의 영역
    

'PivotTable ===============================================================================================
'pt.TableRange1 : 보고서 필터 영역은 제외한 전체 피벗 영역
'pt.TableRange2 : 보고서 필터를 포함한 전체 피벗 영역
'pt.PageRange : 보고서 필터 라벨과 드롭다운 박스 영역
'               PageField가 없을 경우엔 에러 발생
'pt.RowRange : F, G, J 영역
'              RowField가 없을 경우엔 에러 발생
'pt.ColumnRange : B, D, E 영역, B를 포함하므로 RowGrand의 컬럼 위치가 DataBodyRange의 컬럼 수보다 작을 경우엔 DataBodyRange 마지막 컬럼 영역까지 가게 된다.
'                 ColumnField가 없을 경우엔 에러 발생
'pt.DataBodyRange : H, I, K, L 영역
'                   DataField가 없을 경우엔 에러 발생
'pt.DataLabelRange : 데이터필드가 1개일 때는 C영역 1번째 셀, 데이터필드가 2개 이상일 때는 시그마 표시가 있는 부분의 라벨 영역


'PivotField ===============================================================================================
'pf.LabelRange : B나 F의 드롭다운 박스 위치
'pf.DataRange 1) ColumnField의 경우 RowGrand가 True이고 B의 영역보다 작은 경우(묶인 경우) RowGrand를 포함, 아니면 포함하지 아니함
'             2) RowField의 경우 ColumnGrand가 True이면, ColumnGrand를 제외한 영역


'PivotItem ===============================================================================================
'pi.LabelRange : 해당 아이템의 LabelRange
'pi.DataRange : RowGrand와 ColumnGrand는 제외한 pi의 DataBodyRange












'===================================================================================
Function func_Pivot_isDataExist(pPt As PivotTable) As Boolean
'2013-11-05 JUN,YOUNG-WOOK
'OLAP 결과가 존재하는지 빈 깡통 상태인지 파악
    Dim pCache As PivotCache
    Set pCache = pPt.PivotCache
    If pCache.RecordCount > 0 Then
        func_Pivot_isDataExist = True
    Else
        func_Pivot_isDataExist = False
    End If
End Function


Function func_Pivot_Month_Count(pPt As PivotTable) As Long
'2013-11-05 JUN,YOUNG-WOOK
'주로 차트쪽 관련해서 월의 개수를 파악해서 처리하는 루틴들이 많으므로
'월의 개수를 보다 쉽게 파악할 수 있도록 함수를 만듬
'UNION ALL로 붙인 "Total"은 개수에서 제외됨
    Dim pPf As PivotField
    Dim pPi As PivotItem
    Dim isMonthExist As Boolean
    Dim cntMonth As Long
    
    For Each pPf In pPt.PivotFields
        If UCase(pPf.Name) = "MONTH" Then
            isMonthExist = True
            Exit For
        End If
    Next pPf
    
    If isMonthExist Then
        For Each pPi In pPf.PivotItems
            If UCase(pPi.Name) = "JAN" Or UCase(pPi.Name) = "FEB" Or UCase(pPi.Name) = "MAR" Or _
               UCase(pPi.Name) = "APR" Or UCase(pPi.Name) = "MAY" Or UCase(pPi.Name) = "JUN" Or _
               UCase(pPi.Name) = "JUL" Or UCase(pPi.Name) = "AUG" Or UCase(pPi.Name) = "SEP" Or _
               UCase(pPi.Name) = "OCT" Or UCase(pPi.Name) = "NOV" Or UCase(pPi.Name) = "DEC" Then
                    cntMonth = cntMonth + 1
            End If
        Next pPi
        func_Pivot_Month_Count = cntMonth
    Else
        func_Pivot_Month_Count = 0
    End If
End Function
'===================================================================================







Function func_Pivot_DataBodyRange(pPt As PivotTable) As Range
'2013-11-05 JUN,YOUNG-WOOK
'피벗의 H 영역을 리턴하는 함수 (RowGrand와 ColumnGrand를 제외한 순수 데이터 영역)
'아래 (*) 영역의 Range를 리턴

    '       | Year    | Month     | Week    |
    '       |- 2013   | Total     |         |
    '       |+ Oct    |           |         |
    'Region |
    '----------------------------------------
    'CHINA  |10(*)    | 10        |         |   'cntRow = 1
    'Total  |10       | 10        |         |
    '        cntCol = 1

    Dim pPf As PivotField, pPi As PivotItem
    Dim rngResult As Range
    Dim rngColumnLabel As Range, rngRowLabel As Range
    Dim cntColumnFields As Long, cntRowFields As Long, cntDataFields As Long
    Dim cntCol As Long, cntRow As Long
    Dim isRowGrand As Boolean, isColumnGrand As Boolean
    
    cntColumnFields = pPt.ColumnFields.Count    '열필드의 개수
    cntRowFields = pPt.RowFields.Count          '행필드의 개수
    cntDataFields = pPt.DataFields.Count        '데이터필드의 개수
    isRowGrand = pPt.RowGrand                   '행Total의 존재 여부
    isColumnGrand = pPt.ColumnGrand             '열Total의 존재 여부
    
    '데이터필드가 없을 경우엔 void 리턴
    If cntDataFields = 0 Then
        Set rngResult = Nothing
        GoTo commHandle
    End If
    
    
    '행필드, 열필드 모두 없을 경우
    If cntColumnFields = 0 And cntRowFields = 0 Then
        Set rngResult = pPt.DataBodyRange
    
    '열필드만 없을 경우
    ElseIf cntColumnFields = 0 Then
        Set rngResult = Intersect(pPt.DataBodyRange, pPt.DataBodyRange.Offset(IIf(isColumnGrand, -1, 0), 0))
        
    '행필드만 없을 경우 혹은 행필드, 열필드 모두 존재할 경우
    Else
        '1번째 열필드를 찾고
        For Each pPf In pPt.ColumnFields
            If pPf.Position = 1 Then Exit For
        Next pPf

        '1번째 열필드의 LabelRange 파악
        Set rngColumnLabel = pPf.PivotItems(1).LabelRange
        For Each pPi In pPf.PivotItems
            Set rngColumnLabel = Union(rngColumnLabel, pPi.LabelRange)
        Next pPi

        'LabelRange의 컬럼 개수 파악
        cntCol = rngColumnLabel.Columns.Count
        
        '행의 개수 파악
        '행필드 X, 열필드 O
        If cntRowFields = 0 Then
            cntRow = pPt.DataBodyRange.rows.Count   '무조건 1이 나올테고
        '행필드 O, 열필드 O
        Else
            cntRow = pPt.DataBodyRange.rows.Count + IIf(isColumnGrand, -1, 0)
        End If

        '결과 영역
        Set rngResult = pPt.DataBodyRange(1).Resize(cntRow, cntCol)
    End If
    
    
commHandle:
    Set func_Pivot_DataBodyRange = rngResult

End Function

Sub Test_H()
    Dim pPt As PivotTable
    Dim rngH As Range
    
    Set pPt = ActiveSheet.PivotTables(1)
    Set rngH = func_Pivot_DataBodyRange(pPt)
    
    If Not rngH Is Nothing Then
        Debug.Print "func_Pivot_DataBodyRange = " & rngH.Address
    Else
        Debug.Print "Range is Nothing"
    End If
End Sub







Function func_Pivot_RowGrand_DataRange(pPt As PivotTable) As Range
'2013-11-05 JUN,YOUNG-WOOK
'피벗의 I 영역을 리턴하는 함수
'아래 (*) 영역의 Range를 리턴

    '       | Year    | Month     | Week    |
    '       |- 2013   | Total     |         |
    '       |+ Oct    |           |         |
    'Region |
    '----------------------------------------
    'CHINA  |10       | 10(*)     |         |   'cntRow = 1
    'Total  |10       | 10        |         |
    '                   cntCol = 1
    
    Dim pPf As PivotField, pPi As PivotItem
    Dim rngResult As Range
    Dim rngColumnLabel As Range, rngRowLabel As Range
    Dim cntColumnFields As Long, cntRowFields As Long, cntDataFields As Long
    Dim cntCol As Long, cntRow As Long
    Dim isRowGrand As Boolean, isColumnGrand As Boolean
    
    cntColumnFields = pPt.ColumnFields.Count    '열필드의 개수
    cntRowFields = pPt.RowFields.Count          '행필드의 개수
    cntDataFields = pPt.DataFields.Count        '데이터필드의 개수
    isRowGrand = pPt.RowGrand                   '행Total의 존재 여부
    isColumnGrand = pPt.ColumnGrand             '열Total의 존재 여부
    
    '데이터필드가 없을 경우, 행Total이 없는 경우엔 void 리턴
    If cntDataFields = 0 Or isRowGrand = False Then
        Set rngResult = Nothing
        GoTo commHandle
    End If
    
    
    '행필드, 열필드 모두 없을 경우
    If cntColumnFields = 0 And cntRowFields = 0 Then
        Set rngResult = Nothing
    
    '열필드만 없을 경우
    ElseIf cntColumnFields = 0 Then
        Set rngResult = Nothing
        
    '행필드만 없을 경우 혹은 행필드, 열필드 모두 존재할 경우
    Else
        '1번째 열필드를 찾고
        For Each pPf In pPt.ColumnFields
            If pPf.Position = 1 Then Exit For
        Next pPf

        '1번째 열필드의 LabelRange 파악
        Set rngColumnLabel = pPf.PivotItems(1).LabelRange
        For Each pPi In pPf.PivotItems
            Set rngColumnLabel = Union(rngColumnLabel, pPi.LabelRange)
        Next pPi

        'LabelRange의 컬럼 개수 파악
        cntCol = rngColumnLabel.Columns.Count
        
        '행의 개수 파악
        '행필드 X, 열필드 O
        If cntRowFields = 0 Then
            cntRow = pPt.DataBodyRange.rows.Count   '무조건 1이 나올테고
        '행필드 O, 열필드 O
        Else
            cntRow = pPt.DataBodyRange.rows.Count + IIf(isColumnGrand, -1, 0)
        End If

        '결과 영역
        Set rngResult = pPt.DataBodyRange(1).Offset(0, cntCol).Resize(cntRow, 1)
    End If
    
    
commHandle:
    Set func_Pivot_RowGrand_DataRange = rngResult

End Function

Sub Test_I()
    Dim pPt As PivotTable
    Dim rngI As Range
    
    Set pPt = ActiveSheet.PivotTables(1)
    Set rngI = func_Pivot_RowGrand_DataRange(pPt)
    
    If Not rngI Is Nothing Then
        Debug.Print "func_Pivot_RowGrand_DataRange = " & rngI.Address
    Else
        Debug.Print "Range is Nothing"
    End If
End Sub








Function func_Pivot_ColumnGrand_DataRange(pPt As PivotTable) As Range
'2013-11-05 JUN,YOUNG-WOOK
'피벗의 K 영역을 리턴하는 함수
'아래 (*) 영역의 Range를 리턴

    '       | Year    | Month     | Week    |
    '       |- 2013   | Total     |         |
    '       |+ Oct    |           |         |
    'Region |
    '----------------------------------------
    'CHINA  |10       | 10        |         |
    'Total  |10(*)    | 10        |         |    'cntRow = 1
    '        cntCol = 1
    
    Dim pPf As PivotField, pPi As PivotItem
    Dim rngResult As Range
    Dim rngColumnLabel As Range, rngRowLabel As Range
    Dim cntColumnFields As Long, cntRowFields As Long, cntDataFields As Long
    Dim cntCol As Long, cntRow As Long
    Dim isRowGrand As Boolean, isColumnGrand As Boolean
    
    cntColumnFields = pPt.ColumnFields.Count    '열필드의 개수
    cntRowFields = pPt.RowFields.Count          '행필드의 개수
    cntDataFields = pPt.DataFields.Count        '데이터필드의 개수
    isRowGrand = pPt.RowGrand                   '행Total의 존재 여부
    isColumnGrand = pPt.ColumnGrand             '열Total의 존재 여부
    
    '데이터필드가 없을 경우, 열Total이 없는 경우엔 void 리턴
    If cntDataFields = 0 Or isColumnGrand = False Then
        Set rngResult = Nothing
        GoTo commHandle
    End If
    
    
    '행필드, 열필드 모두 없을 경우
    If cntColumnFields = 0 And cntRowFields = 0 Then
        Set rngResult = Nothing
    
    '열필드만 없을 경우
    ElseIf cntColumnFields = 0 Then
        Set rngResult = pPt.DataBodyRange(pPt.DataBodyRange.Cells.Count)
        
    '행필드만 없을 경우
    ElseIf cntRowFields = 0 Then
        Set rngResult = Nothing
        
    '행필드, 열필드 모두 존재할 경우
    Else
        '1번째 열필드를 찾고
        For Each pPf In pPt.ColumnFields
            If pPf.Position = 1 Then Exit For
        Next pPf

        '1번째 열필드의 LabelRange 파악
        Set rngColumnLabel = pPf.PivotItems(1).LabelRange
        For Each pPi In pPf.PivotItems
            Set rngColumnLabel = Union(rngColumnLabel, pPi.LabelRange)
        Next pPi

        'LabelRange의 컬럼 개수 파악
        cntCol = rngColumnLabel.Columns.Count
        
        '행의 개수 파악
        cntRow = pPt.DataBodyRange.rows.Count - 1   'ColumnGrand가 존재하므로 -1

        '결과 영역
        Set rngResult = pPt.DataBodyRange(1).Offset(cntRow, 0).Resize(1, cntCol)
    End If
    
    
commHandle:
    Set func_Pivot_ColumnGrand_DataRange = rngResult

End Function

Sub Test_K()
    Dim pPt As PivotTable
    Dim rngK As Range
    
    Set pPt = ActiveSheet.PivotTables(1)
    Set rngK = func_Pivot_ColumnGrand_DataRange(pPt)
    
    If Not rngK Is Nothing Then
        Debug.Print "func_Pivot_ColumnGrand_DataRange = " & rngK.Address
    Else
        Debug.Print "Range is Nothing"
    End If
End Sub







Function func_Pivot_GrandTotal_DataRange(pPt As PivotTable) As Range
'2013-11-05 JUN,YOUNG-WOOK
'피벗의 L 영역을 리턴하는 함수
'아래 (*) 영역의 Range를 리턴

    '       | Year    | Month     | Week    |
    '       |- 2013   | Total     |         |
    '       |+ Oct    |           |         |
    'Region |
    '----------------------------------------
    'CHINA  |10       | 10        |         |
    'Total  |10       | 10(*)     |         |    'cntRow = 1
    '                   cntCol = 1
    
    Dim pPf As PivotField, pPi As PivotItem
    Dim rngResult As Range
    Dim rngColumnLabel As Range, rngRowLabel As Range
    Dim cntColumnFields As Long, cntRowFields As Long, cntDataFields As Long
    Dim cntCol As Long, cntRow As Long
    Dim isRowGrand As Boolean, isColumnGrand As Boolean
    
    cntColumnFields = pPt.ColumnFields.Count    '열필드의 개수
    cntRowFields = pPt.RowFields.Count          '행필드의 개수
    cntDataFields = pPt.DataFields.Count        '데이터필드의 개수
    isRowGrand = pPt.RowGrand                   '행Total의 존재 여부
    isColumnGrand = pPt.ColumnGrand             '열Total의 존재 여부
    
    '데이터필드가 없을 경우, 열Total 혹은 행Total이 없는 경우엔 void 리턴
    If cntDataFields = 0 Or (isColumnGrand * isRowGrand) = 0 Then
        Set rngResult = Nothing
        GoTo commHandle
    End If
    
    
    '행필드 혹은 열필드가 없을 경우
    If cntColumnFields = 0 Or cntRowFields = 0 Then
        Set rngResult = Nothing
    
    '행필드, 열필드 모두 존재할 경우
    Else
        '1번째 열필드를 찾고
        For Each pPf In pPt.ColumnFields
            If pPf.Position = 1 Then Exit For
        Next pPf

        '1번째 열필드의 LabelRange 파악
        Set rngColumnLabel = pPf.PivotItems(1).LabelRange
        For Each pPi In pPf.PivotItems
            Set rngColumnLabel = Union(rngColumnLabel, pPi.LabelRange)
        Next pPi

        'LabelRange의 컬럼 개수 파악
        cntCol = rngColumnLabel.Columns.Count
        
        '행의 개수 파악
        cntRow = pPt.DataBodyRange.rows.Count - 1   'ColumnGrand가 존재해야 여기까지 오므로 -1

        '결과 영역
        Set rngResult = pPt.DataBodyRange(1).Offset(cntRow, cntCol)
    End If
    
    
commHandle:
    Set func_Pivot_GrandTotal_DataRange = rngResult

End Function

Sub Test_L()
    Dim pPt As PivotTable
    Dim rngL As Range
    
    Set pPt = ActiveSheet.PivotTables(1)
    Set rngL = func_Pivot_GrandTotal_DataRange(pPt)
    
    If Not rngL Is Nothing Then
        Debug.Print "func_Pivot_GrandTotal_DataRange = " & rngL.Address
    Else
        Debug.Print "Range is Nothing"
    End If
End Sub






Sub Example_Union_I_AND_L()
'I와 L영역을 묶어서 리턴하기
    Dim pt As PivotTable
    Set pt = ActiveSheet.PivotTables(1)
    Dim rngI As Range
    Dim rngL As Range
    Dim rngIL As Range
    
    Set rngI = func_Pivot_RowGrand_DataRange(pt)
    Set rngL = func_Pivot_GrandTotal_DataRange(pt)
    
    If Not rngI Is Nothing Then
        If Not rngL Is Nothing Then
            Set rngIL = Union(rngI, rngL)
        Else
            Set rngIL = rngI
        End If
    Else
        Set rngIL = Nothing 'I는 없고, L만 존재하는 경우는 없음
    End If
            
            
    If Not rngIL Is Nothing Then
        Debug.Print rngIL.Address
    Else
        Debug.Print "Nothing"
    End If
End Sub








Function func_Pivot_RowGrand_LabelRange(pPt As PivotTable) As Range
'2013-11-05 JUN,YOUNG-WOOK
'피벗의 E 영역을 리턴하는 함수 [행Total의 맨 위 Total 표시부분]
'아래 (*) 영역의 Range를 리턴

    '       | Year    | Month     | Week    |
    '       |- 2013   | Total(*)  |         |    'cntRow = 2
    '       |+ Oct    |      (*)  |         |
    'Region |
    '----------------------------------------
    'CHINA  |10       | 10        |         |
    'Total  |10       | 10        |         |
    '                   cntCol = 1
    
    Dim pPf As PivotField, pPi As PivotItem
    Dim rngResult As Range
    Dim rngColumnLabel As Range, rngRowLabel As Range
    Dim cntColumnFields As Long, cntRowFields As Long, cntDataFields As Long
    Dim cntCol As Long, cntRow As Long
    Dim isRowGrand As Boolean, isColumnGrand As Boolean
    
    cntColumnFields = pPt.ColumnFields.Count    '열필드의 개수
    cntRowFields = pPt.RowFields.Count          '행필드의 개수
    cntDataFields = pPt.DataFields.Count        '데이터필드의 개수
    isRowGrand = pPt.RowGrand                   '행Total의 존재 여부
    isColumnGrand = pPt.ColumnGrand             '열Total의 존재 여부
    
    '데이터필드가 없을 경우, 행Total이 없는 경우엔 void 리턴
    If cntDataFields = 0 Or isRowGrand = False Then
        Set rngResult = Nothing
        GoTo commHandle
    End If
    
    
    '행필드, 열필드 모두 없을 경우
    If cntColumnFields = 0 And cntRowFields = 0 Then
        Set rngResult = Nothing
    
    '열필드만 없을 경우
    ElseIf cntColumnFields = 0 Then
        Set rngResult = Nothing
        
    '행필드만 없을 경우 혹은 행필드, 열필드 모두 존재할 경우
    Else
        '1번째 열필드를 찾고
        For Each pPf In pPt.ColumnFields
            If pPf.Position = 1 Then Exit For
        Next pPf

        '1번째 열필드의 LabelRange 파악
        Set rngColumnLabel = pPf.PivotItems(1).LabelRange
        For Each pPi In pPf.PivotItems
            Set rngColumnLabel = Union(rngColumnLabel, pPi.LabelRange)
        Next pPi

        'LabelRange의 컬럼 개수 파악
        cntCol = rngColumnLabel.Columns.Count
        
        '행의 개수 파악
        cntRow = cntColumnFields

        '결과 영역
        Set rngResult = rngColumnLabel(1).Offset(0, cntCol).Resize(cntRow, 1)
    End If
    
    
commHandle:
    Set func_Pivot_RowGrand_LabelRange = rngResult

End Function

Sub Test_E()
    Dim pPt As PivotTable
    Dim rngE As Range
    
    Set pPt = ActiveSheet.PivotTables(1)
    Set rngE = func_Pivot_RowGrand_LabelRange(pPt)
    
    If Not rngE Is Nothing Then
        Debug.Print "func_Pivot_RowGrand_LabelRange = " & rngE.Address
    Else
        Debug.Print "Range is Nothing"
    End If
End Sub








Function func_Pivot_ColumnGrand_LabelRange(pPt As PivotTable) As Range
'2013-11-05 JUN,YOUNG-WOOK
'피벗의 J 영역을 리턴하는 함수  [열Total의 맨 왼쪽 Total 표시부분]
'아래 (*) 영역의 Range를 리턴

    '       | Year    | Month     | Week    |
    '       |- 2013   | Total     |         |
    '       |+ Oct    |           |         |
    'Region |
    '----------------------------------------
    'CHINA  |10       | 10        |         |
    'Tota(*)|10       | 10        |         |   'cntRow = 1
    'cntCol = 1
    
    Dim pPf As PivotField, pPi As PivotItem
    Dim rngResult As Range
    Dim rngColumnLabel As Range, rngRowLabel As Range
    Dim cntColumnFields As Long, cntRowFields As Long, cntDataFields As Long
    Dim cntCol As Long, cntRow As Long
    Dim isRowGrand As Boolean, isColumnGrand As Boolean
    
    cntColumnFields = pPt.ColumnFields.Count    '열필드의 개수
    cntRowFields = pPt.RowFields.Count          '행필드의 개수
    cntDataFields = pPt.DataFields.Count        '데이터필드의 개수
    isRowGrand = pPt.RowGrand                   '행Total의 존재 여부
    isColumnGrand = pPt.ColumnGrand             '열Total의 존재 여부
    
    '데이터필드가 없을 경우, 열Total이 없는 경우엔 void 리턴
    If cntDataFields = 0 Or isColumnGrand = False Then
        Set rngResult = Nothing
        GoTo commHandle
    End If
    
    
    '행필드, 열필드 모두 없을 경우
    If cntColumnFields = 0 And cntRowFields = 0 Then
        Set rngResult = Nothing
    
    '행필드만 없을 경우
    ElseIf cntRowFields = 0 Then
        Set rngResult = Nothing
        
    '열필드만 없거나, 행필드, 열필드 모두 존재할 경우
    Else
        Set rngRowLabel = pPt.RowRange

        'LabelRange의 컬럼 개수 파악
        cntRow = rngRowLabel.rows.Count
        
        '행의 개수 파악
        cntCol = rngRowLabel.Columns.Count

        '결과 영역
        Set rngResult = rngRowLabel(1).Offset(cntRow - 1, 0).Resize(1, cntCol)  'ColumnGrand=true이므로, RowRange의 맨 아랫줄은 Total 영역임.
    End If
    
    
commHandle:
    Set func_Pivot_ColumnGrand_LabelRange = rngResult

End Function


Sub Test_J()
    Dim pPt As PivotTable
    Dim rngJ As Range
    
    Set pPt = ActiveSheet.PivotTables(1)
    Set rngJ = func_Pivot_ColumnGrand_LabelRange(pPt)
    
    If Not rngJ Is Nothing Then
        Debug.Print "func_Pivot_ColumnGrand_LabelRange = " & rngJ.Address
    Else
        Debug.Print "Range is Nothing"
    End If
End Sub










Function func_Pivot_ColumnField_LabelRange(pPt As PivotTable) As Range
'2013-11-05 JUN,YOUNG-WOOK
'피벗의 D 영역을 리턴하는 함수
'아래 (*) 영역의 Range를 리턴

    '       | Year    | Month     | Week    |
    '       |- 2013(*)| Total     |         |   'cntRow = 2
    '       |+ Oct (*)|           |         |
    'Region |
    '----------------------------------------
    'CHINA  |10       | 10        |         |
    'Tota   |10       | 10        |         |
    '        cntCol = 1
    
    Dim pPf As PivotField, pPi As PivotItem
    Dim rngResult As Range
    Dim rngColumnLabel As Range, rngRowLabel As Range
    Dim cntColumnFields As Long, cntRowFields As Long, cntDataFields As Long
    Dim cntCol As Long, cntRow As Long
    Dim isRowGrand As Boolean, isColumnGrand As Boolean
    
    cntColumnFields = pPt.ColumnFields.Count    '열필드의 개수
    cntRowFields = pPt.RowFields.Count          '행필드의 개수
    cntDataFields = pPt.DataFields.Count        '데이터필드의 개수
    isRowGrand = pPt.RowGrand                   '행Total의 존재 여부
    isColumnGrand = pPt.ColumnGrand             '열Total의 존재 여부
    
    '데이터필드가 없을 경우
    If cntDataFields = 0 Then
        If cntColumnFields = 0 And cntRowFields = 0 Then
            Set rngResult = Nothing
        ElseIf cntRowFields = 0 Then
        
            cntRow = cntColumnFields
            cntCol = pPt.TableRange1.Columns.Count - 1 '행필드 위치에 컬럼 하나를 차지하므로
            Set rngResult = pPt.TableRange1(1).Offset(1, 1).Resize(cntRow, cntCol)
            
        ElseIf cntColumnFields = 0 Then
            cntRow = 1
            cntCol = pPt.TableRange1.Columns.Count - cntRowFields
            Set rngResult = pPt.TableRange1(1).Offset(1, 1).Resize(cntRow, cntCol)
        
        Else
            cntRow = cntColumnFields
            cntCol = pPt.TableRange1.Columns.Count - cntRowFields
            Set rngResult = pPt.TableRange1(1).Offset(1, cntRowFields).Resize(cntRow, cntCol)
        
        End If
        
        GoTo commHandle
    End If
    
    
    
    '행필드, 열필드 모두 없을 경우
    If cntColumnFields = 0 And cntRowFields = 0 Then
        Set rngResult = Nothing
    
    '열필드만 없을 경우
    ElseIf cntColumnFields = 0 Then
        Set rngResult = pPt.DataBodyRange(1).Offset(-1, 0)
        
    '행필드만 없을 경우 혹은 행필드, 열필드 모두 존재할 경우
    Else
        '1번째 열필드를 찾고
        For Each pPf In pPt.ColumnFields
            If pPf.Position = 1 Then Exit For
        Next pPf

        '1번째 열필드의 LabelRange 파악
        Set rngColumnLabel = pPf.PivotItems(1).LabelRange
        For Each pPi In pPf.PivotItems
            Set rngColumnLabel = Union(rngColumnLabel, pPi.LabelRange)
        Next pPi

        'LabelRange의 컬럼 개수 파악
        cntCol = rngColumnLabel.Columns.Count
        
        '행의 개수 파악
        cntRow = cntColumnFields

        '결과 영역
        Set rngResult = rngColumnLabel(1).Resize(cntRow, cntCol)
    End If
    
    
commHandle:
    Set func_Pivot_ColumnField_LabelRange = rngResult

End Function

Sub Test_D()
    Dim pPt As PivotTable
    Dim rngD As Range
    
    Set pPt = ActiveSheet.PivotTables(1)
    
    Set rngD = func_Pivot_ColumnField_LabelRange(pPt)

    If Not rngD Is Nothing Then
        Debug.Print "func_Pivot_ColumnField_LabelRange = " & rngD.Address
    Else
        Debug.Print "Range is Nothing"
    End If
End Sub







Function func_Pivot_RowField_LabelRange(pPt As PivotTable) As Range
'2013-11-05 JUN,YOUNG-WOOK
'피벗의 D 영역을 리턴하는 함수
'아래 (*) 영역의 Range를 리턴

    '       | Year    | Month     | Week    |
    '       |- 2013   | Total     |         |
    '       |+ Oct    |           |         |
    'Region |
    '----------------------------------------
    'CHIN(*)|10       | 10        |         |   'cntRow = 1
    'Tota   |10       | 10        |         |
    'cntCol = 1
    
    Dim pPf As PivotField, pPi As PivotItem
    Dim rngResult As Range
    Dim rngColumnLabel As Range, rngRowLabel As Range
    Dim cntColumnFields As Long, cntRowFields As Long, cntDataFields As Long
    Dim cntCol As Long, cntRow As Long
    Dim isRowGrand As Boolean, isColumnGrand As Boolean
    
    cntColumnFields = pPt.ColumnFields.Count    '열필드의 개수
    cntRowFields = pPt.RowFields.Count          '행필드의 개수
    cntDataFields = pPt.DataFields.Count        '데이터필드의 개수
    isRowGrand = pPt.RowGrand                   '행Total의 존재 여부
    isColumnGrand = pPt.ColumnGrand             '열Total의 존재 여부
    
    '데이터필드가 없을 경우
    If cntDataFields = 0 Then
        If cntColumnFields = 0 And cntRowFields = 0 Then
            cntRow = pPt.TableRange1.rows.Count - 1
            Set rngResult = pPt.TableRange1(1).Offset(1, 0).Resize(cntRow, 1)
        ElseIf cntRowFields = 0 Then
            cntRow = pPt.TableRange1.rows.Count - cntColumnFields - 1
            cntCol = 1
            Set rngResult = pPt.TableRange1(1).Offset(cntColumnFields + 1, 0).Resize(cntRow, cntCol)
        
            
        ElseIf cntColumnFields = 0 Then
            cntRow = pPt.TableRange1.rows.Count - 2
            cntCol = cntRowFields
            Set rngResult = pPt.TableRange1(1).Offset(2, 0).Resize(cntRow, cntCol)
        
        Else
            cntRow = pPt.TableRange1.rows.Count - cntColumnFields - 1
            cntCol = cntRowFields
            Set rngResult = pPt.TableRange1(1).Offset(cntColumnFields + 1, 0).Resize(cntRow, cntCol)
        
        End If
        
        GoTo commHandle
    End If
    
    
    
    '행필드, 열필드 모두 없을 경우
    If cntColumnFields = 0 And cntRowFields = 0 Then
        Set rngResult = pPt.DataBodyRange(1).Offset(0, -1)
    
    '행필드만 없을 경우
    ElseIf cntRowFields = 0 Then
        Set rngResult = pPt.DataBodyRange(1).Offset(0, -1)
                
    '열필드만 없을 경우 or 행필드, 열필드 모두 존재할 경우
    Else
        cntRow = pPt.RowRange.rows.Count - 1 - IIf(isColumnGrand, 1, 0)
        cntCol = cntRowFields
        Set rngResult = pPt.RowRange(1).Offset(1, 0).Resize(cntRow, cntCol)

    End If
    
    
commHandle:
    Set func_Pivot_RowField_LabelRange = rngResult

End Function

Sub Test_G()
    Dim pPt As PivotTable
    Dim rngG As Range
    
    Set pPt = ActiveSheet.PivotTables(1)
    
    Set rngG = func_Pivot_RowField_LabelRange(pPt)

    If Not rngG Is Nothing Then
        Debug.Print "func_Pivot_RowField_LabelRange = " & rngG.Address
    Else
        Debug.Print "Range is Nothing"
    End If
End Sub







Function func_Pivot_C_Range(pPt As PivotTable) As Range
'2013-11-05 JUN,YOUNG-WOOK
'피벗의 C 영역을 리턴하는 함수
'아래 (*) 영역의 Range를 리턴

    '       | Year    | Month     | Week    |
    '(*)    |- 2013   | Total     |         |   'cntRow = 2
    '(*)    |+ Oct    |           |         |
    'Region |
    '----------------------------------------
    'CHINA  |10       | 10        |         |
    'Total  |10       | 10        |         |
    'cntCol = 1
    
    Dim pPf As PivotField, pPi As PivotItem
    Dim rngResult As Range
    Dim rngColumnLabel As Range, rngRowLabel As Range
    Dim cntColumnFields As Long, cntRowFields As Long, cntDataFields As Long
    Dim cntCol As Long, cntRow As Long
    Dim isRowGrand As Boolean, isColumnGrand As Boolean
    
    cntColumnFields = pPt.ColumnFields.Count    '열필드의 개수
    cntRowFields = pPt.RowFields.Count          '행필드의 개수
    cntDataFields = pPt.DataFields.Count        '데이터필드의 개수
    isRowGrand = pPt.RowGrand                   '행Total의 존재 여부
    isColumnGrand = pPt.ColumnGrand             '열Total의 존재 여부
    
    '데이터필드가 없을 경우
    If cntDataFields = 0 Then
        If cntColumnFields = 0 And cntRowFields = 0 Then
            Set rngResult = Nothing
        ElseIf cntRowFields = 0 Then
            cntRow = cntColumnFields
            cntCol = 1
            Set rngResult = pPt.TableRange1(1).Offset(1, 0).Resize(cntRow, cntCol)
        
            
        ElseIf cntColumnFields <= 1 Then   '열필드가 2개보다 작으면 이 영역은 나오질 못한다.
            Set rngResult = Nothing
        Else
            cntRow = cntColumnFields - 1
            cntCol = cntRowFields
            Set rngResult = pPt.TableRange1(1).Offset(1, 0).Resize(cntRow, cntCol)
        
        End If
        
        GoTo commHandle
    End If
    
    
    
    '행필드, 열필드 모두 없을 경우
    If cntColumnFields = 0 And cntRowFields = 0 Then
        Set rngResult = Nothing
    
    '행필드만 없을 경우
    ElseIf cntRowFields = 0 Then
        cntRow = cntColumnFields
        Set rngResult = pPt.TableRange1(1).Offset(1, 0).Resize(cntRow, 1)
                
    '열필드만 없을 경우
    ElseIf cntColumnFields <= 1 Then
        Set rngResult = Nothing
        
    '행필드, 열필드 모두 존재할 경우
    Else
        cntRow = cntColumnFields - 1
        cntCol = cntRowFields
        Set rngResult = pPt.TableRange1(1).Offset(1, 0).Resize(cntRow, cntCol)

    End If
    
    
commHandle:
    Set func_Pivot_C_Range = rngResult

End Function



Sub Test_C()
    Dim pPt As PivotTable
    Dim rngC As Range
    
    Set pPt = ActiveSheet.PivotTables(1)
    
    Set rngC = func_Pivot_C_Range(pPt)

    If Not rngC Is Nothing Then
        Debug.Print "func_Pivot_C_Range = " & rngC.Address
    Else
        Debug.Print "Range is Nothing"
    End If
End Sub








Function func_Pivot_F_Range(pPt As PivotTable) As Range
'2013-11-05 JUN,YOUNG-WOOK
'피벗의 F 영역을 리턴하는 함수
'아래 (*) 영역의 Range를 리턴

    '       | Year    | Month     | Week    |
    '       |- 2013   | Total     |         |   'cntRow = 2
    '       |+ Oct    |           |         |
    'Regi(*)|
    '----------------------------------------
    'CHINA  |10       | 10        |         |
    'Total  |10       | 10        |         |
    'cntCol = 1
    
    Dim pPf As PivotField, pPi As PivotItem
    Dim rngResult As Range
    Dim rngColumnLabel As Range, rngRowLabel As Range
    Dim cntColumnFields As Long, cntRowFields As Long, cntDataFields As Long
    Dim cntCol As Long, cntRow As Long
    Dim isRowGrand As Boolean, isColumnGrand As Boolean
    
    cntColumnFields = pPt.ColumnFields.Count    '열필드의 개수
    cntRowFields = pPt.RowFields.Count          '행필드의 개수
    cntDataFields = pPt.DataFields.Count        '데이터필드의 개수
    isRowGrand = pPt.RowGrand                   '행Total의 존재 여부
    isColumnGrand = pPt.ColumnGrand             '열Total의 존재 여부
    

    '행필드가 없는 경우
    If cntRowFields = 0 Then
        Set rngResult = Nothing
    
    Else
        Set rngResult = pPt.RowRange.rows(1)
    End If
    
    
commHandle:
    Set func_Pivot_F_Range = rngResult

End Function



Sub Test_F()
    Dim pPt As PivotTable
    Dim rngF As Range
    
    Set pPt = ActiveSheet.PivotTables(1)
    
    Set rngF = func_Pivot_F_Range(pPt)

    If Not rngF Is Nothing Then
        Debug.Print "func_Pivot_F_Range = " & rngF.Address
    Else
        Debug.Print "Range is Nothing"
    End If
End Sub
